package cn.acup.boot.config.shiro;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
 
/**
 * @description: shiro 配置类
 */
//@Configuration
public class ShiroConfig {
 
    // @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
    	shiroFilterFactoryBean.setLoginUrl("/login");
    	// 登录成功后要跳转的链接
    	shiroFilterFactoryBean.setSuccessUrl("/index");
    	// 未授权界面;
    	shiroFilterFactoryBean.setUnauthorizedUrl("/403");
    	
        //拦截器
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // swagger
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/swagger**/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        
        // 配置不会被拦截的链接 顺序判断
    	filterChainDefinitionMap.put("/static/**", "anon");
    	filterChainDefinitionMap.put("/ajaxLogin", "anon");
    	// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
    	filterChainDefinitionMap.put("/logout", "logout");
    	// 
    	// 可替换为通过数据库查询的权限
    	/**  从数据库获取
    	 * List<SysPermissionInit> list = sysPermissionInitService.selectAll();
	    	for (SysPermissionInit sysPermissionInit : list) {
	    		filterChainDefinitionMap.put(sysPermissionInit.getUrl(),
	    				sysPermissionInit.getPermissionInit());
	    	}
    	 */
    	filterChainDefinitionMap.put("/add", "perms[权限添加]");
    	// <!-- 过滤链定义，从上向下顺序执行，一般将 /**放在最为下边 -->:这是一个坑呢，一不小心代码就不好使了;
    	// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
    	filterChainDefinitionMap.put("/**", "authc");
        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
        filterMap.put("jwt", new JwtFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        //<!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边
        filterChainDefinitionMap.put("/**", "jwt");
 
 
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
 
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 
        return shiroFilterFactoryBean;
    }
 
    // @Bean("securityManager")
    public SecurityManager securityManager(MyRealm myRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm);
        // 自定义缓存实现 使用redis
//    	securityManager.setCacheManager(cacheManager());
    	// 自定义session管理 使用redis
//    	securityManager.setSessionManager(SessionManager());
    	//注入记住我管理器;
//        securityManager.setRememberMeManager(rememberMeManager());
 
        /*
         * 关闭shiro自带的session，详情见文档
         * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
 
        return securityManager;
    }
    
    /**
	 * 配置shiro redisManager
	 * 
	 * @return
	 */
//	public RedisManager redisManager() {
//		RedisManager redisManager = new RedisManager();
//		redisManager.setHost(host);
//		redisManager.setPort(port);
//		redisManager.setExpire(1800);// 配置过期时间
//		// redisManager.setTimeout(timeout);
//		// redisManager.setPassword(password);
//		return redisManager;
//	}
//	/**
//	 * cacheManager 缓存 redis实现
//	 * 
//	 * @return
//	 */
//	public RedisCacheManager cacheManager() {
//		RedisCacheManager redisCacheManager = new RedisCacheManager();
//		redisCacheManager.setRedisManager(redisManager());
//		return redisCacheManager;
//	}
//	/**
//	 * RedisSessionDAO shiro sessionDao层的实现 通过redis
//	 */
//	public RedisSessionDAO redisSessionDAO() {
//		RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
//		redisSessionDAO.setRedisManager(redisManager());
//		return redisSessionDAO;
//	}
//	/**
//	 * shiro session的管理
//	 */
//	public DefaultWebSessionManager SessionManager() {
//		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//		sessionManager.setSessionDAO(redisSessionDAO());
//		return sessionManager;
//	}
// redis参考： https://blog.csdn.net/cckevincyh/article/details/79633661
    
//    /**
//     * cookie对象;
//     * @return
//     */
//    public SimpleCookie rememberMeCookie(){
//       //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
//       SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//       //<!-- 记住我cookie生效时间30天 ,单位秒;-->
//       simpleCookie.setMaxAge(2592000);
//       return simpleCookie;
//    }
//    /**
//     * cookie管理对象;记住我功能
//     * @return
//     */
//    public CookieRememberMeManager rememberMeManager(){
//       CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
//       cookieRememberMeManager.setCookie(rememberMeCookie());
//       //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
//       cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
//       return cookieRememberMeManager;
//    }

//<!-- shiro+redis缓存插件 -->
//<dependency>
//	<groupId>org.crazycake</groupId>
//	<artifactId>shiro-redis</artifactId>
//	<version>2.4.2.1-RELEASE</version>
//</dependency>
}

